
    use: 'ie.ondevice.objectkit.utility.compiler.idiom.Idiom';

    ClassWriter.implement
    (
        {
            /**
             * @private
             * @type {Array}
             */
            idioms: null
            
            /**
             * TODO deprecate in favour of the idiom strategy approach
             */
        ,   enableDebugger: function () 
            {
                this.debug= true;
            }
            
            /**
             * TODO deprecate
             */
        ,   disableDebugger: function () 
            {
                this.debug= false;
            }
            
            /**
             * Disable the class writer. No classes will be written to.
             * @return {void}
             */
        ,   disable: function () 
            {
                this.enabled= false;
            }
             
            /**
             * Enable the class writer. 
             * @return {void}
             */
        ,   enable: function () 
            {
                this.enabled= true;
            }
            
            /**
             * Determine whether the class writer is enabled or not
             * @return {Boolean}
             * @see #enable
             * @see #disable
             */
        ,   isEnabled: function () 
            {
                return true === this.enabled;
            }
            
            /**
             * Transform a class files sourceCode. The transformed code
             * will become the value of the class files #sourceCode property.
             * Class files will be transformed in this order
             *     
             *     import expressions
             *     export expressions
             *     package expressions
             *     header expression
             *     debugger expression
             * 
             * @param {ClassFile} classFile
             * @return {void}
             * 
             * TODO - add and remove idioms rather than explicit methods
             */
        ,   write: function (classFile) 
            {
                if (false === this.isEnabled())
                    return;
                
                this.writeImports(classFile);
                this.writeExports(classFile);
                this.writePackage(classFile);
                this.writeHeaderComment(classFile);
                this.writeDebuggerStatement(classFile);
                
                /* // TODO implement
                for (var i= 0, n= this.idioms.length, idiom; i < n; i++) 
                {
                    try 
                    {
                        idiom= this.idioms[i];
                        idiom.setWriter(this);
                        idiom.express(classFile);
                    }
                    catch (thrown)
                    {
                        
                    }
                }
                */
            }
            
            /**
             * Add an idiom to the class writer. Idioms are processed in order
             * of addition. Adding an already added idiom will modify its
             * order by taking it from its original position, and demoting
             * it to the last position.
             * 
             * @param {Object} value
             */
        ,   addIdiom: function (value) 
            {
                this.removeIdiom(value);
                this.idioms.push(value);
                value.setWriter(this);
            }
            
            /**
             * Remove an idiom. The class writer will no longer write
             * the idiom to the class file
             * 
             * @param {Object} value
             * @return {void}
             */
        ,   removeIdiom: function (value) 
            {
                this.idioms.remove(value);
            }
            
            /**
             * Retrieve the idioms in use by this writer
             * @return {Array.<Idiom>}
             */
        ,   getIdioms: function () 
            {
                return this.idioms.concat();
            }
            
            /**
             * Express an idiom in a class file.
             * @param {String} name            An idioms name
             * @param {ClassFile} classFile    The class file to write to
             * @return {void}
             * @throws {Error}    If the idiom cannot be retrieved
             * @see #addIdiom
             * @see #removeIdiom
             * @see #getIdiom
             */
        ,   writeIdiom: function (name, classFile) 
            {
                this.getIdiom(name).express(classFile);
            }
            
            /**
             * Get an idiom registered with this class writer.
             * @param {String} name    An idioms name
             * @return {Idiom}
             * @throws {Error} If the idiom cannot be retrieved
             * @see #addIdiom
             * @see #removeIdiom
             */
        ,   getIdiom: function (name) 
            {
                var idiom;
                for (var i= 0, n= this.idioms.length; i < n; i++) 
                {
                    idiom= this.idioms[i];
                    if (name === idiom.name)
                        return idiom;
                }
                
                throw new Error ('Unknown idiom ' + name);
            }

            /**
             * Write a header comment idiom on top of the file.
             * @param {Object} value
             * @return {void}
             */
        ,   writeHeaderComment: function (classFile) 
            {
                var comment= '\n//@ sourceURL=' + classFile.canonicalName;
                classFile.sourceCode= comment + classFile.sourceCode;
            }
            
            /**
             * Write an import statement idiom into a class files source code
             * @param {ClassFile} classFile
             * @return {void}
             * TODO deprecate
             */
        ,   writeImports: function (classFile) 
            {
                var dependencies= classFile.getDependencies()
                ,   canonicalName
                ,   sourceCode= classFile.sourceCode
                ,   dependency
                ,   i= 0
                ,   n= dependencies.length
                ,   imports= []
                
                if (0 === n)
                    return;
                
                for (; i < n; i++) 
                {
                    dependency= this.provider.getClass(dependencies[i]);
                    imports.push(dependency.localName + '=' + dependency.canonicalName);
                }    
                
                classFile.sourceCode= '\nvar ' +imports.join('\n,    ') + ';\n' + sourceCode;
            }  
            
            /**
             * TODO deprecate
             * Write a declaration idiom expressing all the objects that
             * this classFile will export into the class files source code
             * 
             * @param {ClassFile} classFile    The class file to write to.
             * @return {void}
             */
        ,   writeExports: function (classFile) 
            {
                classFile.sourceCode+= '\nRuntime.declare("' 
                + classFile.canonicalName + '", ' + classFile.localName + ');'
            } 
            
            /**
             * TODO deprecate
             * Write a package idiom.
             * @param {ClassFile} classFile    The class file to write to.
             * @return {void}
             */
        ,   writePackage: function (classFile) 
            {
                classFile.sourceCode= '\n(function(){\n'
                + classFile.sourceCode
                + '\n})();\n'
            }
            
            /**
             * TODO deprecate
             * Write a debugger idom.
             * @param {ClassFile} classFile    The class file to write to
             * @return {void}
             */
        ,   writeDebuggerStatement: function (classFile) 
            {
                if (this.debug)
                    classFile.sourceCode= '\ndebugger;' + classFile.sourceCode;
            }
            
            /**
             * Set the writers class provider. The class provider will be used
             * to pull in contextual information that any class file may
             * require. A class provider must implement a method with the
             * signature 
             * 
             * @param {Object} value
             * @return {void}
             */
        ,   setClassProvider: function (value) 
            {
                this.provider= value;
            }
        }
    );
    
    /**
     * Create a new class writer. The class writer will express any idioms that
     * it knows of the source code of any class file passed to its write
     * method. Writing to a class file does not write to disk- source files
     * will always remain unmodified.
     * 
     * @constructor
     */
    function ClassWriter () 
    {
        this.setClassProvider
        (
            {
                getClass: function (canonicalName) 
                {
                    throw new Error ('No provider available to retrieve ' 
                        + canonicalName);
                }
            }
        );
        
        this.enable();
    };
